(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('hy5b/t')) :
    typeof define === 'function' && define.amd ? define(['t'], factory) :
    global.t = factory(t);
}(this, function(T) {
  var document = window.document;

  var id = function(sid) {
    return document.getElementById(sid);
  };

  var escapeReg = function(str) {
    return str.replace(new RegExp("([.*+?^=!:\x24{}()|[\\]\/\\\\])", "g"), "\\\x241");
  };

  var getByClass = function(sclassname, dparent, stagname) {
    if (document.getElementsByClassName) {
      //Todo:增加 dparent, stagname 的筛选
      var nodes = (dparent || document).getElementsByClassName(sclassname),
        results = [];
      for (var i = 0; i < nodes.length; i++) {
        if (stagname && (nodes[i].tagName.toUpperCase() !== stagname.toUpperCase())) {
          continue;
        }
        //(new ctest()).add(sclassname, nodes[i].className);
        results.push(nodes[i]);
      }
      return results;
    } else {
      stagname = stagname || "*";
      var nodes = (dparent || document).getElementsByTagName(stagname),
        results = [];
      for (var i = 0; i < nodes.length; i++) {
        if (sclassname && nodes[i].className && nodes[i].className.indexOf(sclassname) != -1) {
          //(new ctest()).add(sclassname, nodes[i].className);
          results.push(nodes[i]);
        }
      }
      return results;
    }
  };

  T.extend({
    id: id,
    c2ds: getByClass,
    hasClass: function(elem, className) {
      className = className || '';
      if (className.replace(/\s/g, '').length == 0) return false;
      return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
    },
    addClass: function(elem, className) {
      if (!this.hasClass(elem, className)) {
        elem.className = elem.className == '' ? className : elem.className + ' ' + className;
      }
    },
    removeClass: function(elem, className) {
      if (this.hasClass(elem, className)) {
        var newClassName = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' ';
        while (newClassName.indexOf(' ' + className + ' ') >= 0) {
          newClassName = newClassName.replace(' ' + className + ' ', ' ');
        }
        elem.className = newClassName.replace(/^\s+|\s+$/g, '');
      }
    },
    /**
     * [eachObject description]
     * @param {[type]} obj   [description]
     * @param {[type]} fCall [function(key, value, index, self)]
     */
    eachObject: function(obj, fcall) {
      if (this.isObject(obj)) {
        var i = 0;
        for (var param in obj) {
          fcall(param, obj[param], i, obj);
          i++;
        }
      }
    },
    eachArray: function(array, fcall) {
      if (this.isArray(array)) {
        if (array.forEach)
          array.forEach(fcall);
        else {
          for (var i = 0; i < array.length; i++)
            fcall(array[i], i, array);
        }
      }
    },
    every: function(array, fcall) {
      if (array.every)
        return array.every(fcall);
      else {
        var bret;
        for (var i = 0; i < array.length; i++) {
          bret = fcall(array[i], i, array);
          if (!bret)
            return false;
        }
        return true;
      }
    },
    getInnerText: function(dom) {
      return (typeof dom.textContent == "string") ? dom.textContent : dom.innerText;
    },
    escapeHtml: function(str) {
      if (str != "" && typeof str === "string") {
        return str.replace(/[&<> ]/g, function(word) {
          var otags = {
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            " ": "&nbsp;"
          };
          return otags[word] || word;
        });
      } else if (typeof str === "number")
        return str;
      else
        return "";
    },
    addSelectItem: function(dom, show, val) {
      for (var i = 0; i < dom.options.length; i++) {
        if (dom.options[i].value == val)
          return i;
      }
      dom.options[dom.options.length] = new Option(show, val);
      return (dom.options.length - 1);
    },
    setSelectItem: function(dom, val) {
      for (var i = 0; i < dom.options.length; i++) {
        if (dom.options[i].value == val) {
          dom.options[i].selected = true;
          return i;
        }
      }
      return -1;
    },
    initSelectItem: function(dom, aval, ftransShow) {
      dom.options.length = 0;
      if (ftransShow != undefined) {
        for (var i = 0; i < aval.length; i++)
          dom.options[i] = new Option(ftransShow(aval[i], i), aval[i]);
      } else {
        for (var i = 0; i < aval.length; i++)
          dom.options[i] = new Option(aval[i], aval[i]);
      }
    },
    findSelectValue: function(dom, sval) {
      for (var i = 0; i < dom.options.length; i++) {
        if (dom.options[i].value == sval)
          return i;
      }
      return -1;
    },
    findSelectText: function(dom, stext) {
      for (var i = 0; i < dom.options.length; i++) {
        if (this.getInnerText(dom.options[i]) == stext)
          return i;
      }
      return -1;
    },
    splitTrimBlank: function(str, sdelim, subdelim) {
      var vbj = null;
      if (str == null)
        return [];
      var atemp = str.split(sdelim);

      if (subdelim == null) {
        vbj = [];
        for (var i = 0; i < atemp.length; i++) {
          if (atemp[i] != "")
            vbj.push(atemp[i]);
        }
      } else {
        vbj = {};
        for (var i = 0; i < atemp.length; i++) {
          if (atemp[i] != "") {
            var asubtemp = atemp[i].split(subdelim);
            vbj[asubtemp[0]] = asubtemp[1];
          }
        }
      }
      return vbj;
    },
    /**
     * 删除URL字符串中指定的 pair
     * @param {String} url URL字符串
     * @param {String} key 被删除的pair名
     * @return {String} 被删除指定 pair 后的URL字符串
     */
    deleteUrlPair: function(surl, skey) {
      skey = escapeReg(skey);
      var rtmp = new RegExp("((\\?)(" + skey + "=[^&]*&)+(?!" + skey + "=))|(((\\?|&)" + skey + "=[^&]*)+$)|(&" + skey + "=[^&]*)", "g");
      return surl.replace(rtmp, "\x241");
    },
    mouseWheel: function(elem, listener, useCapture) {
      if (elem.addEventListener) {
        elem.addEventListener('DOMMouseScroll', listener, useCapture);//firefox
        elem.addEventListener('mousewheel', listener, useCapture);//chrome
      } else if (elem.attachEvent) {
        elem.attachEvent('onmousewheel', listener);
      } else {
        //IE/Opera/Chrome/Safari
        window.onmousewheel = document.onmousewheel = listener;
      }
    },
    eventPosition: function(eve) {
      var left, top;
      if (eve.pageX) {
        left = eve.pageX;
        top = eve.pageY;
      } else if (eve.x) {
        left = eve.x;
        top = eve.y;
      } else {
        left = eve.screenX;
        top = eve.screenY;
      }
      return {
        X: left,
        Y: top
      };
    },
    eventTarget: function(eve) {
      if (eve.target)
        return eve.target;
      else if (eve.srcElement)
        return eve.srcElement;
    },
    addEvent: function(dom, sevent, func) {
      if (!dom)
        return;
      if (dom.addEventListener) {
        dom.addEventListener(sevent, func, false); //非ie 和ie9
      } else if (dom.attachEvent) {
        dom.attachEvent("on" + sevent, func); //ie6到ie8
      } else {
        dom["on" + sevent] = func; //ie5
      }
    },
    removeEvent: function(dom, sevent, func) {
      if (!dom)
        return;
      if (dom.removeEventListener) {
        dom.removeEventListener(sevent, func, false);
      } else if (dom.detachEvent) {
        dom.detachEvent("on" + sevent, func);
      } else {
        dom["on" + sevent] = null;
      }
    },
    val: function(sid) {
      var dom = id(sid);
      if (dom)
        return dom.value;
      else
        return "";
    },
    isEmptyObj: function(obj) {
      for (var param in obj)
        return false;
      return true;
    },
    getScrollPos: function(dom) {
      var win = null,
        x = 0,
        y = 0;

      if (!dom || dom && typeof dom === "object" && "setInterval" in dom) {
        win = window;
        if ("PageXOffset" in win) {
          x = win.pageXOffset;
          y = win.pageYOffset;
        } else {
          x = win.document.documentElement.scrollLeft || win.document.body.scrollLeft;
          y = win.document.documentElement.scrollTop || win.document.body.scrollTop;
        }
      } else {
        x = dom.scrollLeft;
        y = dom.scrollTop;
      }
      return { x: x, y: y };
    },
    formatFileSize: function(num) {
      if (isNaN(num)) {
        return false;
      }
      num = parseInt(num);
      var units = [" B", " KB", " MB", " GB"];
      for (var i = 0; i < units.length; i += 1) {
        if (num < 1024) {
          num = num + "";
          if (num.indexOf(".") != -1 && num.indexOf(".") != 3) {
            num = num.substring(0, 4);
          } else {
            num = num.substring(0, 3);
          }
          break;
        } else {
          num = num / 1024;
        }
      }
      return num + units[i];
    },
    removeValue: function(array, val) {
      var pos = -1;
      if (array.indexOf) {
        pos = array.indexOf(val);
      } else {
        for (var i = 0; i < array.length; i++) {
          if (array[i] === val)
            pos = i;
        }
      }

      if (pos !== -1) {
        array.splice(pos, 1);
        return array;
      }
      return array;
    },
    iframeAppendHtml(elem, html) {
      var elemDocument = elem.contentDocument || elem.contentWindow.document;
      elemDocument.open();
      elemDocument.write(html);
      elemDocument.close();
    }
  });

  var doc = document
  var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement
  var baseElement = head.getElementsByTagName("base")[0]

  var currentlyAddingScript

  function request(url, callback, charset) {
    var node = doc.createElement("script")

    if (charset) {
      var cs = isFunction(charset) ? charset(url) : charset
      if (cs) {
        node.charset = cs
      }
    }

    addOnload(node, callback, url)

    node.async = true
    node.src = url

    // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
    // the end of the insert execution, so use `currentlyAddingScript` to
    // hold current node, for deriving url in `define` call
    currentlyAddingScript = node

    // ref: #185 & http://dev.jquery.com/ticket/2709
    baseElement ?
      head.insertBefore(node, baseElement) :
      head.appendChild(node)

    currentlyAddingScript = null
  }

  function addOnload(node, callback, url) {
    var supportOnload = "onload" in node

    if (supportOnload) {
      node.onload = onload
      node.onerror = function() {
        emit("error", { uri: url, node: node })
        onload(true)
      }
    } else {
      node.onreadystatechange = function() {
        if (/loaded|complete/.test(node.readyState)) {
          onload()
        }
      }
    }

    function onload(error) {
      // Ensure only run once and handle memory leak in IE
      node.onload = node.onerror = node.onreadystatechange = null

      // Dereference the node
      node = null

      callback(error)
    }
  }

  function loadjs(basePath) {
    this.path_ = this.base_ = basePath || "";
  }

  loadjs.prototype.base = function(basePath) {
    if (basePath != undefined)
      this.base_ = this.path_ + basePath;
    return this;
  }

  loadjs.prototype.load = function(alink, cb) {
    if (typeof alink === 'string')
      alink = [alink];
    var ascript = [],
      acss = [];
    for (var i = 0; i < alink.length; i++) {
      if (/\.js$/.test(alink[i]))
        ascript.push(alink[i]);
      else if (/\.css$/.test(alink[i]))
        acss.push(alink[i]);
    }
    if (acss.length > 0)
      this.loadCss(acss);
    if (ascript.length > 0)
      this.loadScript(ascript, cb);
    return this;
  }

  loadjs.prototype.loadCss = function(alink) {
    if (typeof alink === "string")
      alink = [alink];
    var elems = document.createDocumentFragment();
    for (var i = 0; i < alink.length; i++) {
      var dlink = document.createElement("link");
      dlink.rel = 'stylesheet';
      dlink.href = this.base_ + alink[i];
      elems.appendChild(dlink);
    }
    document.getElementsByTagName("head")[0].appendChild(elems);
    return this;
  };

  loadjs.prototype.loadScript = function(alink, callback) {
    if (typeof alink === "string")
      alink = [alink];
    var base = this.base_;
    if (callback) {
      T.recursive(function(i, call) {
        request(base + alink[i], call);
      }, alink, 0, function(error) {
        callback(error);
      });
    } else {
      var elems = document.createDocumentFragment();
      for (var i = 0; i < alink.length; i++) {
        var dscript = document.createElement("script");
        dscript.src = base + alink[i];
        elems.appendChild(dscript);
      }
      document.getElementsByTagName("head")[0].appendChild(elems);
    }
    return this;
  }

  T.load = function(base) {
    return new loadjs(base);
  };
  return T;
}));
